package com.swf.seed.triutil.compress;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream;
import org.apache.commons.compress.compressors.CompressorException;
import org.apache.commons.compress.compressors.CompressorInputStream;
import org.apache.commons.compress.compressors.CompressorOutputStream;
import org.apache.commons.compress.compressors.CompressorStreamFactory;
import org.apache.commons.compress.utils.IOUtils;
import org.apache.commons.io.FilenameUtils;

public class SdCompressUtils {
	public static final int BUFFERSIZE = 8024; //buffer的size为8K字节
	
	/**
	 * @param destFile
	 *            压缩后文件
	 * @param srcFile
	 *            原文件
	 * @param compressorType
	 *            压缩类型 @See
	 *            CompressorStreamFactory.GZIP,CompressorStreamFactory.BZIP2
	 * @throws IOException
	 * @throws CompressorException
	 */
	public static void doCompress(File destFile, File srcFile, String compressorType) throws IOException, CompressorException {
		InputStream is = null;
		CompressorOutputStream cos = null;
		try {
			is = new BufferedInputStream(new FileInputStream(srcFile), BUFFERSIZE);
			cos = new CompressorStreamFactory().createCompressorOutputStream(compressorType, new BufferedOutputStream(new FileOutputStream(destFile), BUFFERSIZE));
			IOUtils.copy(is, cos, BUFFERSIZE);
		} finally {
			IOUtils.closeQuietly(is);
			IOUtils.closeQuietly(cos);
		}
	}
 
	    public static void doDecompress(File destFile,File srcFile,String compressorType) throws IOException, CompressorException {  
	    	CompressorInputStream cis = null;  
	        OutputStream bos = null;  
	        try {  
	            cis = new CompressorStreamFactory().createCompressorInputStream(compressorType,new BufferedInputStream(new FileInputStream(srcFile), BUFFERSIZE));
	            bos = new BufferedOutputStream(new FileOutputStream(destFile), BUFFERSIZE);  
	            IOUtils.copy(cis, bos);  
	        } finally {  
	            IOUtils.closeQuietly(cis);  
	            IOUtils.closeQuietly(bos);  
	        }  
	    } 
	    
	    /**
	     * @param destFile 压缩后文件
	     * @param srcFile 需要压缩的文件或目录
	     * @param includeRootDir 根目录是否需要保留
	     * @throws IOException 
	     * @throws CompressorException
	     */
	    public static void tar(File destFile,File srcFile,boolean includeRootDir) throws IOException, CompressorException{
	    	List<File> fileList = getFiles(srcFile);
	    	tarFiles(destFile,fileList,includeRootDir?srcFile.getParent():srcFile.getAbsolutePath());
	    }
	    
	    /**
	     * 递归获取所有文件
	     * @param file 文件或者目录
	     * @return
	     */
	    public static List<File> getFiles(File file){
	    	List<File> fileList = new ArrayList<File>();
	    	fileList.add(file);
	    	if (file.isDirectory()){
	    		for (File f:file.listFiles()){
	    			fileList.addAll(getFiles(f));
	    		}
	    	}
	    	return fileList;
	    	
	    }
	    
	    /**
	     * @param srcFileList 需要压缩的文件列表
	     * @param destFile 压缩后文件
	     * @param compressorType 
	     * 压缩类型 @See CompressorStreamFactory.GZIP,CompressorStreamFactory.BZIP2
	     * @throws IOException
	     * @throws CompressorException
	     */
	    public static void tarFiles(File destFile,List<File> srcFileList,String rootPath) throws IOException, CompressorException {  
	    	TarArchiveOutputStream tos = null;
	    	InputStream bis = null;  
	        try {  
	        	tos = new TarArchiveOutputStream(new BufferedOutputStream(new FileOutputStream(destFile), BUFFERSIZE));
	        	rootPath = FilenameUtils.separatorsToUnix(rootPath);
	        	for (File srcFile:srcFileList){
		            TarArchiveEntry entry = new TarArchiveEntry(srcFile,FilenameUtils.separatorsToUnix(srcFile.getAbsolutePath()).replaceAll(rootPath, "")); 
		            tos.putArchiveEntry(entry); 
		            System.out.println(entry.getFile());
		            if (srcFile.isFile()){
		            	entry.setSize(srcFile.length());  
		            	bis = new BufferedInputStream(new FileInputStream(srcFile), BUFFERSIZE);  
		            	System.out.println(IOUtils.copy(bis, tos,BUFFERSIZE));
		            }
		            tos.closeArchiveEntry();
	        	}
	        	tos.finish();
	        } finally {
	            IOUtils.closeQuietly(bis);  
	            IOUtils.closeQuietly(tos);  
	        }  
	    }  
	    /**
	     * 解压tar文件
	     * @param destDir  解压目标目录
	     * @param srcFile  解压的文件
	     * @throws IOException
	     * @throws CompressorException
	     */
	    public static void untar(File destDir, File srcFile) throws IOException, CompressorException {  
	    	TarArchiveInputStream tais = null;  
	    	BufferedInputStream bis = null;
	        try {  
	            tais = new TarArchiveInputStream(new BufferedInputStream(new FileInputStream(srcFile), BUFFERSIZE));  
	            TarArchiveEntry entry = null;  
	            while ((entry = tais.getNextTarEntry()) != null) {  
	                if (entry.isDirectory()) {  
	                    File directory = new File(destDir, entry.getName());  
	                    directory.mkdirs();  
	                } else {  
	                    BufferedOutputStream bos = null;  
	                    try {
	                    	File tmpFile = new File(destDir, entry.getName());
	                    	if (!tmpFile.getParentFile().exists()){
	                    		tmpFile.getParentFile().mkdirs();
	                    	}
	                    	tmpFile.createNewFile();
	                        bos = new BufferedOutputStream(new FileOutputStream(  
	                        		tmpFile), BUFFERSIZE); 
	                        int readbytes;  
	                        byte[] buffer = new byte[BUFFERSIZE];  
	                        while ((readbytes = tais.read(buffer))!=-1) {  
	                        	bos.write(buffer, 0, readbytes);  
	                        }
	                        bos.flush();
	                    } finally {  
	                        IOUtils.closeQuietly(bos);  
	                    }  
	                }  
	            }  
	        } finally {  
	            IOUtils.closeQuietly(bis);  
	            IOUtils.closeQuietly(tais);  
	        }  
	    } 
	    
	    
	    
	    
	    
	public static void main(String[] args) throws CompressorException, IOException {
		tar(new File("d:/linux/a.tar"),new File("d:/linux/test/"),true);
		doCompress(new File("d:/linux/a.tar.gz"), new File("d:/linux/a.tar"), CompressorStreamFactory.GZIP);
		doDecompress(new File("d:/linux/c.tar"), new File("d:/linux/a.tar.gz"), CompressorStreamFactory.GZIP);
		untar(new File("d:/linux/abc"),new File("d:/linux/c.tar") );
	}
}
